
import urllib
import urllib2
import base64
import hmac
import hashlib
import time

from django.shortcuts import render_to_response
from django.http import HttpResponse, HttpResponseRedirect

from django.conf import settings

import oauth
import oauth_settings

from models import Identity


# Create your views here.
def login(request):
    token = request.session.get('token', '')
    
    return render_to_response('gaccounts/login.html', {'token': token})


"""
# this is for old gdata api
def login_authsub_authpage(request):
    import gdata.contacts.service
    
    scope = "http://www.google.com/m8/feeds/"
    callback_url = settings.HOST_URL + '/accounts/callback/'

    api = gdata.contacts.service.ContactsService()
    authpage = api.GenerateAuthSubURL(callback_url, scope)

    return HttpResponseRedirect(authpage)


def login_authsub_callback(request):
    import gdata.contacts.service
    
    service_callback_token = request.GET.get('token')
    token = None

    # todo: valid service_callback_token
    if service_callback_token:

        api = gdata.contacts.service.ContactsService()
        api.auth_token = service_callback_token
        api.UpgradeToSessionToken()

        token = api._GDataService__auth_token

        request.session['token'] = token

    return render_to_response('gaccounts/login_callback.html', {'token': token})
"""

def login_authsub_authpage(request):
    import gdata.contacts.service
    
    scope = "http://www.google.com/m8/feeds/"
    callback_url = oauth_settings.OPENID_RETURN_TO
    
    api = gdata.contacts.service.ContactsService()
    authpage = api.GenerateAuthSubURL(callback_url, scope)
    
    return HttpResponseRedirect(authpage.to_string())


def login_authsub_callback(request):
    import gdata.contacts.service
    
    service_callback_token = request.GET.get('token')
    token = None
    
    # todo: valid service_callback_token
    if service_callback_token:
        api = gdata.contacts.service.ContactsService(http_client = gdata.alt.appengine.AppEngineHttpClient())
        token = AuthSubToken()
        token.set_token_string(service_callback_token)
        api.UpgradeToSessionToken(token)
        
    return render_to_response('gaccounts/login_callback.html', {'token': token.get_token_string()})


def login_openid_authpage(request):
    """
    """
    
    scope = 'http://www.google.com/m8/feeds/'
    callback_url = oauth_settings.OPENID_RETURN_TO
    end_point = 'https://www.google.com/accounts/o8/ud'
    
    paramenters = {}
    paramenters['openid.realm'] = oauth_settings.OPENID_REALM
    paramenters['openid.ns'] = 'http://specs.openid.net/auth/2.0'
    paramenters['openid.mode'] = 'associate'
    paramenters['openid.assoc_type'] = 'HMAC-SHA1'
    paramenters['openid.session_type'] = 'no-encryption'
    
    data = urllib2.urlopen(end_point, urllib.urlencode(paramenters)).read()
    
    for i in data.split('\n'):
        if i.startswith('mac_key:'):
            request.session['mac_key'] = base64.b64decode(i.lstrip('mac_key:'))
        if i.startswith('assoc_handle'):
            assoc_handle = i.lstrip('assoc_handle:')
            
    paramenters = {}
    paramenters['openid.ns'] = 'http://specs.openid.net/auth/2.0'
    paramenters['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select'
    paramenters['openid.identity'] = 'http://specs.openid.net/auth/2.0/identifier_select'
    paramenters['openid.return_to'] = callback_url
    paramenters['openid.realm'] = oauth_settings.OPENID_REALM
    paramenters['openid.assoc_handle'] = assoc_handle
    paramenters['openid.mode'] = 'checkid_setup'
    
    authpage = end_point +'?'+ urllib.urlencode(paramenters)
    
    return HttpResponseRedirect(authpage)


def login_openid_callback(request):
    """
    This is the API endpoint for service to callback with token.
    """
    
    # valid service_callback_token
    signed = request.GET['openid.signed'].split(',')
    data = ''.join([i+':'+request.GET['openid.'+i]+'\n' for i in signed])
    
    token = None
    
    return render_to_response('gaccounts/login_callback.html', {'token': token})


def login_hybird_authpage(request):
    """
    """
    try:
        scope = "http://www.google.com/m8/feeds/"
        end_point = 'https://www.google.com/accounts/o8/ud'
        
        paramenters = {}
        paramenters['openid.realm'] = oauth_settings.OPENID_REALM #important
        paramenters['openid.ns'] = 'http://specs.openid.net/auth/2.0'
        paramenters['openid.mode'] = 'associate'
        paramenters['openid.assoc_type'] = 'HMAC-SHA1'
        paramenters['openid.session_type'] = 'no-encryption'
        
        data = urllib2.urlopen(end_point, urllib.urlencode(paramenters)).read()
        
        for i in data.split('\n'):
            if i.startswith('mac_key:'):
                request.session['mac_key'] = base64.b64decode(i.lstrip('mac_key:'))
            if i.startswith('assoc_handle'):
                assoc_handle = i.lstrip('assoc_handle:')
        
        paramenters = {}
        paramenters['openid.ns'] = 'http://specs.openid.net/auth/2.0'
        paramenters['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select'
        paramenters['openid.identity'] = 'http://specs.openid.net/auth/2.0/identifier_select'
        paramenters['openid.return_to'] = oauth_settings.OPENID_RETURN_TO #important
        paramenters['openid.realm'] = oauth_settings.OPENID_REALM #important
        paramenters['openid.assoc_handle'] = assoc_handle
        paramenters['openid.mode'] = 'checkid_setup'
        
        paramenters['openid.ns.ext1'] = 'http://specs.openid.net/extensions/oauth/1.0'
        paramenters['openid.ext1.consumer'] = oauth_settings.CONSUMER_KEY #important
        paramenters['openid.ext1.scope'] = 'http://www.google.com/m8/feeds/'
        
        paramenters['openid.ns.ext2'] = 'http://openid.net/srv/ax/1.0'
        paramenters['openid.ext2.mode'] = 'fetch_request'
        paramenters['openid.ext2.required'] = 'email'
        paramenters['openid.ext2.type.email'] = 'http://schema.openid.net/contact/email'
        
        authpage = end_point +'?'+ urllib.urlencode(paramenters)
        
        return HttpResponseRedirect(authpage)
    
    except:
        retry = request.session.get('retry', 1) + 1
        time.sleep(0.5*retry)
        if retry > 7:
            request.session['retry'] = 0
            return render_to_response('gaccounts/failed.html')
        request.session['retry'] = retry
        
        return HttpResponseRedirect('/accounts/authpage/')        

def login_hybird_callback(request):
    """
    """
    if str(request.GET.get('openid.mode')) == 'cancel':
        return render_to_response('gaccounts/failed.html')
        
    consumer = oauth.OAuthConsumer(oauth_settings.CONSUMER_KEY, oauth_settings.CONSUMER_SECRET) #important
        
    request_token = ''
    user_email = ''
    
    ns = str(request.GET.get('openid.ns.ext2', ''))
    if ns == 'http://specs.openid.net/extensions/oauth/1.0':
        request_token = oauth.OAuthToken(str(request.GET.get('openid.ext2.request_token')), '')
    
    ns = str(request.GET.get('openid.ns.ext1', ''))
    if ns == 'http://specs.openid.net/extensions/oauth/1.0':
        request_token = oauth.OAuthToken(str(request.GET.get('openid.ext1.request_token')), '')
    elif ns == 'http://openid.net/srv/ax/1.0':
        user_email = str(request.GET.get('openid.ext1.value.email'))
        
    # valid service_callback_token
    signed = request.GET.get('openid.signed', '').split(',')
    data = ''.join([i+':'+request.GET.get('openid.'+i, '')+'\n' for i in signed])
    
    token = None
    if(request.GET.get('openid.sig', '') == base64.b64encode(hmac.new(request.session.get('mac_key', ''), data, hashlib.sha1).digest())):
        # openid successed
        if user_email:
            #put to db
            identity, created = Identity.objects.get_or_create(identity = request.GET.get('openid.identity', ''))
            identity.email = user_email
            identity.save()
            request.session['user_email'] = user_email
        else:
            #load from db
            identity = Identity.objects.get(identity = request.GET.get('openid.identity', ''))
            request.session['user_email'] = identity.email
            print identity.email
        
        url='https://www.google.com/accounts/OAuthGetAccessToken'
        
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, request_token, http_url=url)
        oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, None)
        
        req = urllib2.Request(url, None, oauth_request.to_header())
        
        try:
            token = urllib2.urlopen(req).read()
        except:
            
            retry = request.session.get('retry', 1) + 1
            time.sleep(0.5*retry)
            if retry > 7:
                request.session['retry'] = 0
                return render_to_response('gaccounts/failed.html')
                
            request.session['retry'] = retry
            return HttpResponseRedirect(request.META['PATH_INFO']+'?'+request.META['QUERY_STRING'])
            
        access_token = oauth.OAuthToken.from_string(token)
        request.session['access_token'] = token
        
    request.session['retry'] = 0
    
    return render_to_response('gaccounts/close.html')


def logout_hybird(request):
    if 'user_email' in request.session:
        del request.session['user_email']
        
    if 'access_token' in request.session:
        del request.session['access_token']
        
    if 'mac_key' in request.session:
        request.session['mac_key']
        
    return HttpResponse('Logout!')


def check_hybird(request):
    if 'user_email' in request.session and 'access_token' in request.session and 'mac_key' in request.session:
        return HttpResponse('Login!')
    return HttpResponse('Logout!')
